All files / local indexeddb_remote_document_cache.ts

96.97% Statements 32/33
90% Branches 9/10
100% Functions 11/11
96.67% Lines 29/30
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104                                  2x 2x   2x   2x         2x   2x 339x   2x       563x           2x       60x     1684x       1684x     1684x           121x       121x       121x 121x 121x   83x 83x 1x 82x 47x     121x   2x               2428x 2428x                 2307x    
/**
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
import { Query } from '../core/query';
import { DocumentMap, documentMap } from '../model/collections';
import { Document, MaybeDocument } from '../model/document';
import { DocumentKey } from '../model/document_key';
import { fail } from '../util/assert';
 
import { DbRemoteDocument, DbRemoteDocumentKey } from './indexeddb_schema';
import { LocalSerializer } from './local_serializer';
import { PersistenceTransaction } from './persistence';
import { PersistencePromise } from './persistence_promise';
import { RemoteDocumentCache } from './remote_document_cache';
import { SimpleDbStore, SimpleDbTransaction } from './simple_db';
 
export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache {
  constructor(private serializer: LocalSerializer) {}
 
  addEntry(
    transaction: PersistenceTransaction,
    maybeDocument: MaybeDocument
  ): PersistencePromise<void> {
    return remoteDocumentsStore(transaction).put(
      dbKey(maybeDocument.key),
      this.serializer.toDbRemoteDocument(maybeDocument)
    );
  }
 
  removeEntry(
    transaction: PersistenceTransaction,
    documentKey: DocumentKey
  ): PersistencePromise<void> {
    return remoteDocumentsStore(transaction).delete(dbKey(documentKey));
  }
 
  getEntry(
    transaction: PersistenceTransaction,
    documentKey: DocumentKey
  ): PersistencePromise<MaybeDocument | null> {
    return remoteDocumentsStore(transaction)
      .get(dbKey(documentKey))
      .next(dbRemoteDoc => {
        return dbRemoteDoc
          ? this.serializer.fromDbRemoteDocument(dbRemoteDoc)
          : null;
      });
  }
 
  getDocumentsMatchingQuery(
    transaction: PersistenceTransaction,
    query: Query
  ): PersistencePromise<DocumentMap> {
    let results = documentMap();
 
    // Documents are ordered by key, so we can use a prefix scan to narrow down
    // the documents we need to match the query against.
    const startKey = query.path.toArray();
    const range = IDBKeyRange.lowerBound(startKey);
    return remoteDocumentsStore(transaction)
      .iterate({ range }, (key, dbRemoteDoc, control) => {
        const maybeDoc = this.serializer.fromDbRemoteDocument(dbRemoteDoc);
        if (!query.path.isPrefixOf(maybeDoc.key.path)) {
          control.done();
        } else if (maybeDoc instanceof Document && query.matches(maybeDoc)) {
          results = results.insert(maybeDoc.key, maybeDoc);
        }
      })
      .next(() => results);
  }
}
 
/**
 * Helper to get a typed SimpleDbStore for the remoteDocuments object store.
 */
function remoteDocumentsStore(
  txn: PersistenceTransaction
): SimpleDbStore<DbRemoteDocumentKey, DbRemoteDocument> {
  Eif (txn instanceof SimpleDbTransaction) {
    return txn.store<DbRemoteDocumentKey, DbRemoteDocument>(
      DbRemoteDocument.store
    );
  } else {
    return fail('Invalid transaction object provided!');
  }
}
 
function dbKey(docKey: DocumentKey): DbRemoteDocumentKey {
  return docKey.path.toArray();
}